package br.com.afi.util;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Métodos úteis para formatação.
 * 
 * @author André de Fontana Ignacio
 * @version 1.1
 */
public class Format
{
	/**
	 * Não é possível instanciar essa classe.
	 */
	private Format()
	{
		super();
	}

	/**
	 * Formata o diretório informado inserindo ou retirando as barras no ínicio ou do fim da String
	 * de acordo com os paramêtros informados.
	 * 
	 * @param dir Diretório
	 * @param initialSlash Deve possuir uma barra no ónicio?
	 * @param finalSlash Deve possuir uma barra no final?
	 * @return Diretório formatado
	 */
	public static String formatDirectory( String dir, boolean initialSlash, boolean finalSlash )
	{
		String formatDir = dir;

		if ( initialSlash )
		{
			if ( !formatDir.startsWith( "/" ) )
			{
				formatDir = "/" + formatDir;
			}
			else
			{
				while ( formatDir.startsWith( "//" ) )
				{
					formatDir = formatDir.substring( 1, formatDir.length() );
				}
			}
		}
		else
		{
			while ( formatDir.startsWith( "/" ) )
			{
				formatDir = formatDir.substring( 1, formatDir.length() );
			}
		}

		if ( finalSlash )
		{
			if ( !formatDir.endsWith( "/" ) )
			{
				formatDir = formatDir + "/";
			}
			else
			{
				while ( formatDir.endsWith( "//" ) )
				{
					formatDir = formatDir.substring( 0, formatDir.length() - 1 );
				}
			}
		}
		else
		{
			while ( formatDir.endsWith( "/" ) )
			{
				formatDir = formatDir.substring( 0, formatDir.length() - 1 );
			}
		}

		return formatDir;
	}

	/**
	 * Formata a data de acordo com o pattern informado.
	 * 
	 * @param date Data
	 * @param pattern Pattern seguindo o padrão do SimpleDateFormat
	 * @return Data formatada
	 */
	public static String dateFormat( Date date, String pattern )
	{
		final SimpleDateFormat sdf = new SimpleDateFormat( pattern );
		String stringDate = "";
		if ( date != null )
		{
			stringDate = sdf.format( date );
		}
		return stringDate;
	}

	/**
	 * Converte de texto para data. Se não for possível converter lança RuntimeException. Utilize
	 * este método somente quando tiver certeza que a data informada está correta.
	 * 
	 * @param stringDate Data
	 * @param pattern Formato
	 * @return Data formatada
	 */
	public static Date dateFormatRTE( String stringDate, String pattern )
	{
		final SimpleDateFormat sdf = new SimpleDateFormat( pattern );
		Date date = null;
		if ( stringDate != null && !"".equals( stringDate ) )
		{
			try
			{
				date = sdf.parse( stringDate );
			}
			catch ( ParseException e )
			{
				throw new RuntimeException( e.getMessage(), e );
			}
		}
		return date;
	}

	/**
	 * Converte de texto para data.
	 * 
	 * @param stringDate Data
	 * @param pattern Formato da Data
	 * @return Data formatada
	 * @throws ParseException Lan�ada quando não é possivel formatar a data
	 */
	public static Date dateFormat( String stringDate, String pattern ) throws ParseException
	{
		final SimpleDateFormat sdf = new SimpleDateFormat( pattern );
		Date date = null;
		if ( stringDate != null && !"".equals( stringDate ) )
		{
			date = sdf.parse( stringDate );
		}
		return date;
	}

	/**
	 * Obtém somente a parte de hora da data informada no formato HH:mm.
	 * 
	 * @param date Data
	 * @return Hora em formato (HH:mm)
	 */
	public static String getHour( Date date )
	{
		final SimpleDateFormat sdf = new SimpleDateFormat( "HH:mm" );
		final Calendar calendar = new GregorianCalendar( 0, 0, 0, 0, 0 );
		calendar.setTime( date );
		return sdf.format( date );
	}

	/**
	 * Obtém somente a parte de hora da data informada no formato HH:mm:ss.
	 * 
	 * @param date Data
	 * @return Hora em formato (HH:mm:ss)
	 */
	public static String getFullHour( Date date )
	{
		final SimpleDateFormat sdf = new SimpleDateFormat( "HH:mm:ss" );
		final Calendar calendar = new GregorianCalendar( 0, 0, 0, 0, 0 );
		calendar.setTime( date );
		return sdf.format( date );
	}

	/**
	 * Retorna a String informada somente com a primeira letra maiúscula.
	 * 
	 * @param str String
	 * @return String somente com a primeira letra maiúscula.
	 */
	public static String onlyFirstLetterUpper( String str )
	{
		String ret = "";
		if ( str != null && str.length() > 0 )
		{
			final String firstLetter = str.substring( 0, 1 ).toUpperCase();
			final String restLower = str.substring( 1, str.length() ).toLowerCase();
			ret = firstLetter + restLower;
		}
		return ret;
	}

	/**
	 * Remove os acentos.
	 * 
	 * @param text Texto
	 * @param removeCedilla Remove ç?
	 * @return String sem acento.
	 */
	public static String removeAccents( String text, boolean removeCedilla )
	{
		// ´
		text = text.replaceAll( "á", "a" );
		text = text.replaceAll( "é", "e" );
		text = text.replaceAll( "í", "i" );
		text = text.replaceAll( "ó", "o" );
		text = text.replaceAll( "ú", "u" );
		// `
		text = text.replaceAll( "à", "a" );
		text = text.replaceAll( "è", "e" );
		text = text.replaceAll( "ì", "i" );
		text = text.replaceAll( "ò", "o" );
		text = text.replaceAll( "ù", "u" );
		// ^
		text = text.replaceAll( "â", "a" );
		text = text.replaceAll( "ê", "e" );
		text = text.replaceAll( "î", "i" );
		text = text.replaceAll( "ô", "o" );
		text = text.replaceAll( "û", "u" );
		// ~
		text = text.replaceAll( "ã", "a" );
		text = text.replaceAll( "õ", "o" );
		// ¨
		text = text.replaceAll( "ä", "a" );
		text = text.replaceAll( "ë", "e" );
		text = text.replaceAll( "ï", "i" );
		text = text.replaceAll( "ö", "o" );
		text = text.replaceAll( "ü", "u" );

		// ç
		if ( removeCedilla )
		{
			text = text.replaceAll( "ç", "c" );
		}

		return text;
	}

	/**
	 * Transforma uma string númerica em um número.
	 * 
	 * @param numberStr Número em String
	 * @return Número obtido
	 * @throws ParseException Lançada quando a String não for num número
	 */
	public static Number numberFormat( String numberStr ) throws ParseException
	{
		Number number = null;
		if ( numberStr != null && !"".equals( numberStr ) )
		{
			final NumberFormat nf = NumberFormat.getInstance();
			number = nf.parse( numberStr );
		}
		return number;
	}

	/**
	 * Transforma uma string númerica em um número. Se não for possível converter lança
	 * RuntimeException. Utilize este método somente quando tiver certeza que a String é um número.
	 * 
	 * @param numberStr Número em String
	 * @return Número obtido
	 * @throws ParseException Lançada quando a String não for num número
	 */
	public static Number numberFormatRTE( String numberStr ) throws ParseException
	{
		Number number = null;
		if ( numberStr != null && !"".equals( numberStr ) )
		{
			final NumberFormat nf = NumberFormat.getInstance();
			number = nf.parse( numberStr );
		}
		return number;
	}

	/**
	 * Transforma uma número em uma string númerica com a quantidade de casas decimais informada.
	 * Caso o número informado seja nulo retorna uam String vazia.
	 * 
	 * @param number Número
	 * @param fractionDigits Quantidade de casas decimais
	 * @return String númerica obtida
	 */
	public static String numberFormat( Number number, int fractionDigits )
	{
		String numberStr = null;
		if ( number != null )
		{
			final NumberFormat nf = NumberFormat.getInstance();
			nf.setMaximumFractionDigits( fractionDigits );
			nf.setMinimumFractionDigits( fractionDigits );
			numberStr = nf.format( number );
		}
		else
		{
			numberStr = new String();
		}
		return numberStr;
	}

	/**
	 * Realiza o arredondamento das casas decimais de um número.
	 * 
	 * @param number Número
	 * @param roundType Tipo de Arrendondamento, constants definidas em {@link BigDecimal}
	 * @param fractionDigits Quantidade de casas decimais
	 * @return Número arredondando
	 */
	public static double decimalRound( Number number, int roundType, int fractionDigits )
	{
		BigDecimal bd = new BigDecimal( number.doubleValue() );
		bd = bd.setScale( fractionDigits, roundType );
		return bd.doubleValue();
	}
}
